
#include <helper.h>
#include <material/materialoverviewdialog.h>
#include <material/effecteditor/effectoverview.h>
#include <material/materialeditor/materialoverview.h>
#include <material/programeditor/programoverview.h>
#include <material/shadereditor/shaderoverview.h>
#include <material/textureeditor/textureoverview.h>
#include <qbuttongroup.h>
#include <qmessagebox.h>
#include <qshortcut.h>
#include <qstackedlayout.h>
#include <qtabwidget.h>
#include <config.h>
#include <assert.h>
#include <stdio.h>

cceMaterialOverviewDialog::cceMaterialOverviewDialog (cceMaterialManager *manager, QWidget* parent)
  : QDialog (parent, Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::WindowCloseButtonHint)
  , _manager (manager)
{
	_gui.setupUi(this);

  QFile file (":/style/material/material.qss");
  file.open (QFile::ReadOnly);
  QString style = QLatin1String (file.readAll());
  file.close();
  setStyleSheet(style);


  QGridLayout* contentLayout = new QGridLayout (_gui.widgetEditors);
  _editorTabs = new QTabWidget(_gui.widgetEditors);
  _editorTabs->setTabsClosable(true);
  _editorTabs->setMovable(true);
  contentLayout->addWidget(_editorTabs);

  connect (_editorTabs, SIGNAL(tabCloseRequested(int)), this, SLOT(TabCloseRequested(int)));


	_buttonGroup = new QButtonGroup(this);
	_buttonGroup->addButton(_gui.pushButtonMaterials);
	_buttonGroup->addButton(_gui.pushButtonEffects);
	_buttonGroup->addButton(_gui.pushButtonPrograms);
	_buttonGroup->addButton(_gui.pushButtonShaders);
  _buttonGroup->addButton(_gui.pushButtonTextures);

	_overviewLayout = new QStackedLayout (_gui.frameOverviews);
	_overviewLayout->setContentsMargins (0, 0, 0, 0);

  _materialsOverview = new cceMaterialMaterialOverview (_gui.frameOverviews);
  _overviewLayout->addWidget(_materialsOverview);

  _effectsOverview = new cceMaterialEffectOverview(_gui.frameOverviews);
  _overviewLayout->addWidget(_effectsOverview);

	_programOverview = new cceMaterialProgramOverview (_gui.frameOverviews);
	_overviewLayout->addWidget (_programOverview);

  _shaderOverview = new cceMaterialShaderOverview (_gui.frameOverviews);
  _overviewLayout->addWidget(_shaderOverview);

  _texturesOverview = new cceMaterialTextureOverview (_gui.frameOverviews);
  _overviewLayout->addWidget(_texturesOverview);

  connect (_texturesOverview, SIGNAL(ShowEditor(cceMaterialItem*)), this, SLOT(ShowEditorByOverview(cceMaterialItem*)));
  connect (_shaderOverview, SIGNAL(ShowEditor(cceMaterialItem*)), this, SLOT(ShowEditorByOverview(cceMaterialItem*)));
  connect (_programOverview, SIGNAL(ShowEditor(cceMaterialItem*)), this, SLOT(ShowEditorByOverview(cceMaterialItem*)));
  connect (_effectsOverview, SIGNAL(ShowEditor(cceMaterialItem*)), this, SLOT(ShowEditorByOverview(cceMaterialItem*)));
  connect (_materialsOverview, SIGNAL(ShowEditor(cceMaterialItem*)), this, SLOT(ShowEditorByOverview(cceMaterialItem*)));

  connect (_gui.labelMaterialsMenu, SIGNAL(Save()), this, SLOT(Save()));
  connect (_gui.labelMaterialsMenu, SIGNAL(SaveAll()), this, SLOT(SaveAll()));
  connect (_gui.labelMaterialsMenu, SIGNAL(Export()), this, SLOT(Export()));
  connect (_gui.labelMaterialsMenu, SIGNAL(UpdateGraphicsSystem()), _manager, SLOT(UpdateGraphicsSystem()));
  connect (_gui.labelMaterialsMenu, SIGNAL(Hide()), this, SLOT(reject()));


  QAction *closeTabAction = new QAction(this);
  closeTabAction->setShortcut(QKeySequence (Qt::CTRL + Qt::Key_W));
  addAction(closeTabAction);
  connect (closeTabAction, SIGNAL(triggered()), this, SLOT(CloseTab ()));

  addAction(_gui.labelMaterialsMenu->GetAction(cceMaterialMenuButton::Action_Save));
  addAction(_gui.labelMaterialsMenu->GetAction(cceMaterialMenuButton::Action_Hide));

  _gui.splitterMainOverview->setChildrenCollapsible(true);
  QList<int> sizes;
  sizes << 0 << width();
  _gui.splitterMainOverview->setSizes(sizes);

  _gui.splitterMainOverview->handle(0)->setEnabled(false);

  _editorTabs->setVisible(false);
  connect (_buttonGroup, SIGNAL(buttonClicked(QAbstractButton*)), this, SLOT(ButtonGroupClicked(QAbstractButton*)));

	setModal(false);
	setWindowTitle (" ");

}

void cceMaterialOverviewDialog::reject()
{
  setVisible(false);
}


void cceMaterialOverviewDialog::ButtonGroupClicked (QAbstractButton* button)
{
  if (button == _gui.pushButtonMaterials)
    {
      _overviewLayout->setCurrentIndex(0);
    }
  else if (button == _gui.pushButtonEffects)
    {
      _overviewLayout->setCurrentIndex(1);
    }
  else if (button == _gui.pushButtonPrograms)
    {
      _overviewLayout->setCurrentIndex(2);
    }
  else if (button == _gui.pushButtonShaders)
    {
      _overviewLayout->setCurrentIndex(3);
    }
  else if (button == _gui.pushButtonTextures)
    {
      _overviewLayout->setCurrentIndex(4);
    }
}

void cceMaterialOverviewDialog::Save()
{
  cceMaterialEditorAbstract* widget = static_cast<cceMaterialEditorAbstract*>(_editorTabs->currentWidget());
  if (widget)
    {
      widget->Save();
		}
	_manager->SaveAll();
	_manager->Export();
}

void cceMaterialOverviewDialog::SaveAll()
{
  QMap<cceMaterialItem*, cceMaterialEditorAbstract*>::iterator it;
  for (it = _editors.begin(); it != _editors.end(); ++it)
    {
      cceMaterialEditorAbstract* editor = it.value();
      if (!editor->Save())
        {
          return;
        }
    }
}

void cceMaterialOverviewDialog::Export()
{
  QMap<cceMaterialItem*, cceMaterialEditorAbstract*>::iterator it;
  for (it = _editors.begin(); it != _editors.end(); ++it)
    {
      cceMaterialEditorAbstract* editor = it.value();
      if (!editor->Save())
        {
          return;
        }
    }
  _manager->SaveAll();
  _manager->Export();
}


void cceMaterialOverviewDialog::CloseTab()
{
  cceMaterialEditorAbstract* widget = static_cast<cceMaterialEditorAbstract*>(_editorTabs->currentWidget());
  if (widget)
    {
      widget->Close();
    }
}

void cceMaterialOverviewDialog::TabCloseRequested(int idx)
{
  cceMaterialEditorAbstract* widget = static_cast<cceMaterialEditorAbstract*>(_editorTabs->widget(idx));
  if (widget)
    {
      widget->Close();
    }
}

void cceMaterialOverviewDialog::EditorNameChanged (const QString& name)
{
  cceMaterialEditorAbstract* editor = static_cast<cceMaterialEditorAbstract*>(sender ());
  assert (editor);

  int idx = _editorTabs->indexOf(editor);
  if (idx < 0)
    {
      return;
    }

  _editorTabs->setTabText(idx, name);
}

void cceMaterialOverviewDialog::ShowEditor(cceMaterialItem *item)
{
  if (item)
    {
      ShowEditorEvaluateByType(item);
    }
}

void cceMaterialOverviewDialog::ShowEditorEvaluateByType(cceMaterialItem *item)
{
  switch (item->GetItemType())
    {
    case cceMaterialItem::ItemType_Texture:
      ShowEditor(_texturesOverview, item);
      break;

    case cceMaterialItem::ItemType_Shader:
      ShowEditor(_shaderOverview, item);
      break;

    case cceMaterialItem::ItemType_Program:
      ShowEditor(_programOverview, item);
      break;

    case cceMaterialItem::ItemType_Effect:
      ShowEditor(_effectsOverview, item);
      break;

    case cceMaterialItem::ItemType_Material:
      ShowEditor(_materialsOverview, item);
      break;

    }
}


void cceMaterialOverviewDialog::ShowEditorByOverview(cceMaterialItem* item)
{
  cceMaterialOverviewAbstract* overview = static_cast<cceMaterialOverviewAbstract*>(sender ());
  assert (overview);

  ShowEditor (overview, item);
}

void cceMaterialOverviewDialog::ShowEditor(cceMaterialOverviewAbstract *overview, cceMaterialItem *item)
{

  cceMaterialEditorAbstract* editor = 0;
  QMap<cceMaterialItem*, cceMaterialEditorAbstract*>::iterator it;
  it = _editors.find(item);
  if (it == _editors.end())
    {
      editor = overview->CreateEditor(item);
      editor->SetMaterialMananager(_manager);
      connect (editor, SIGNAL(NameChanged(const QString&)), this, SLOT(EditorNameChanged (const QString&)));
      connect (editor, SIGNAL(CloseEditor(cceMaterialItem*)), this, SLOT(CloseEditor(cceMaterialItem *)));
      connect (editor, SIGNAL(ShowEditor(cceMaterialItem*)), this, SLOT(ShowEditorEvaluateByType(cceMaterialItem*)));
      connect (editor, SIGNAL(SaveTextures()), _manager, SLOT(SaveTextures()));
      connect (editor, SIGNAL(SaveShaders()), _manager, SLOT(SaveShaders()));
      connect (editor, SIGNAL(SavePrograms()), _manager, SLOT(SavePrograms()));
      connect (editor, SIGNAL(SaveEffects()), _manager, SLOT(SaveEffects()));
      connect (editor, SIGNAL(SaveMaterials()), _manager, SLOT(SaveMaterials()));
      _editors[item] = editor;
      _editorTabs->addTab(editor, editor->GetName());

    }
  else
    {
      editor = it.value();
    }
  EnsureEditorsOpen();
  _editorTabs->setCurrentWidget(editor);
}


void cceMaterialOverviewDialog::CloseEditor(cceMaterialItem *item)
{
  QMap<cceMaterialItem*, cceMaterialEditorAbstract*>::iterator it;
  it = _editors.find(item);
  if (it == _editors.end())
    {
      return;
    }

  cceMaterialEditorAbstract* editor = it.value();

  int idx = _editorTabs->indexOf(editor);
  _editorTabs->removeTab(idx);
  _editors.erase(it);

  TryCloseEditors();
}



void cceMaterialOverviewDialog::EnsureEditorsOpen()
{
  int widthEditor = _gui.splitterMainOverview->sizes()[0];
  int widthOverview = _gui.splitterMainOverview->sizes()[1];

	int targetSize = 640;

  if (widthEditor < targetSize)
    {
      int sizeAdd = targetSize - widthEditor;
      QList<int> sizes;
      sizes << targetSize << widthOverview;


      new cceResizeSliderHelper (this, width () + sizeAdd, height());
      new ccePosSliderHelper (this, pos().x() - sizeAdd, pos().y());
      new cceSplitterSliderHelper(_gui.splitterMainOverview, sizes);
      new cceVisibilityHelper(_editorTabs, true);
    }
}


void cceMaterialOverviewDialog::TryCloseEditors()
{
  if (_editors.size() > 0)
    {
      return;
    }

  int widthEditor = _gui.splitterMainOverview->sizes()[0];
  int widthOverview = _gui.splitterMainOverview->sizes()[1];

  int targetWidth = width () - widthEditor;
  QList<int> sizes;
  sizes << 0 << widthOverview;

  _editorTabs->setVisible(false);

  new cceResizeSliderHelper (this, targetWidth, height ());
  new ccePosSliderHelper(this, pos().x() + widthEditor, pos().y());
  new cceSplitterSliderHelper(_gui.splitterMainOverview, sizes);


}



void cceMaterialOverviewDialog::on_labelMaterialsMenu_Clear()
{
  int button = QMessageBox::question(this,
                        "Clear Materials - " CCE_TOOL_NAME,
                        "Are you sure to clear all materials?\nAll changes will get lost.",
                        QMessageBox::Yes,
                        QMessageBox::No
                        );

  if (button == QMessageBox::Yes)
    {
      _manager->Clear();
    }

}
